import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.cluster import KMeans, DBSCAN
from sklearn.decomposition import PCA
from matplotlib import font_manager

# 设置中文字体
font_path = 'C:/Windows/Fonts/simhei.ttf'
my_font = font_manager.FontProperties(fname=font_path)

# 读取数据集
df = pd.read_csv('D:/pycharm/data/ml-latest-small/tags.csv')

# 查看数据集的基本信息
print("数据集基本信息:")
print(df.info())
print("\n数据集前5行:")
print(df.head())

# 检查是否有缺失值
print("\n缺失值统计:")
print(df.isnull().sum())

# 标签的分布情况
print("\n标签的分布情况:")
print(df['tag'].value_counts())

# 独热编码
encoder = OneHotEncoder(sparse=False)
tags_encoded = encoder.fit_transform(df[['tag']])
tags_encoded_df = pd.DataFrame(tags_encoded, columns=encoder.get_feature_names_out(['tag']))

# 将编码后的标签与用户ID合并
df_encoded = pd.concat([df[['userId']], tags_encoded_df], axis=1)

# 查看处理后的数据
print("\n处理后的数据:")
print(df_encoded.head())

# 数据标准化
scaler = StandardScaler()
scaled_data = scaler.fit_transform(df_encoded.drop('userId', axis=1))

# 选择聚类的数量
k = 5

# 进行K-Means聚类
kmeans = KMeans(n_clusters=k, random_state=42)
df_encoded['cluster_kmeans'] = kmeans.fit_predict(scaled_data)

# 进行DBSCAN聚类
dbscan = DBSCAN(eps=0.5, min_samples=5)
df_encoded['cluster_dbscan'] = dbscan.fit_predict(scaled_data)

# 查看聚类结果
print("\nK-Means聚类结果:")
print(df_encoded.groupby('cluster_kmeans').mean())

print("\nDBSCAN聚类结果:")
print(df_encoded.groupby('cluster_dbscan').mean())

# 计算每个聚类的标签数量
kmeans_cluster_counts = df_encoded['cluster_kmeans'].value_counts()
dbscan_cluster_counts = df_encoded['cluster_dbscan'].value_counts()

print("\nK-Means每个聚类的用户数量:")
print(kmeans_cluster_counts)

print("\nDBSCAN每个聚类的用户数量:")
print(dbscan_cluster_counts)

# 可视化K-Means每个聚类的标签数量
plt.figure(figsize=(10, 6))
sns.barplot(x=kmeans_cluster_counts.index, y=kmeans_cluster_counts.values)
plt.title('K-Means每个聚类的用户数量', fontproperties=my_font)
plt.xlabel('聚类', fontproperties=my_font)
plt.ylabel('用户数量', fontproperties=my_font)
plt.xticks(rotation=45)
plt.show()

# PCA降维
pca = PCA(n_components=2)
reduced_data = pca.fit_transform(scaled_data)

# 创建一个新的DataFrame用于可视化
pca_df = pd.DataFrame(data=reduced_data, columns=['PCA1', 'PCA2'])
pca_df['cluster_kmeans'] = df_encoded['cluster_kmeans']
pca_df['cluster_dbscan'] = df_encoded['cluster_dbscan']

# 可视化K-Means聚类的PCA结果
plt.figure(figsize=(10, 6))
sns.scatterplot(x='PCA1', y='PCA2', hue='cluster_kmeans', data=pca_df, palette='viridis', s=100, alpha=0.6)
plt.title('K-Means用户聚类的PCA结果', fontproperties=my_font)
plt.xlabel('PCA 组件 1', fontproperties=my_font)
plt.ylabel('PCA 组件 2', fontproperties=my_font)
plt.legend(title='聚类', prop={'size': 10}, title_fontsize='13')
plt.show()

# 可视化DBSCAN聚类的PCA结果
plt.figure(figsize=(10, 6))
sns.scatterplot(x='PCA1', y='PCA2', hue='cluster_dbscan', data=pca_df, palette='viridis', s=100, alpha=0.6)
plt.title('DBSCAN用户聚类的PCA结果', fontproperties=my_font)
plt.xlabel('PCA 组件 1', fontproperties=my_font)
plt.ylabel('PCA 组件 2', fontproperties=my_font)
plt.legend(title='聚类', prop={'size': 10}, title_fontsize='13')
plt.show()
